﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Resources;
using System.Globalization;
using System.IO;
using blackhouse;
using System.Text;
using System.Collections;
using blackhouse.JavaScript.JQuery;
using System.Web.UI;

namespace blackhouse.JavaScript { 
	public class MultilanguageJsResource {

		#region Fields

		private string resourceFileName;
		private CultureInfo includeLanguage;
		private HttpContext context;
		private DirectoryInfo diJs;
		private FileInfo fiBaseResourceFile;
		private FileInfo fiLangResourceFile;
		private FileInfo jsLangResourceFile;

		#endregion

		#region Constructors

		/// <summary>
		/// Konstruktor klasy dla domyślnego języka
		/// </summary>
		/// <param name="baseResourceFile">Lokalizacja pliku resx. np.: /App_GlobalResources/Resources.resx</param>
		public MultilanguageJsResource(string baseResourceFile) : this(baseResourceFile, CultureInfo.CurrentCulture) { }

		public MultilanguageJsResource(string baseResourceFile, CultureInfo language) {
			this.includeLanguage = language;
			this.context = HttpContext.Current;

			this.SetFileInfos(baseResourceFile);
			this.EnsureSetJsFiles();
			this.IncludeScript();
		}

		#endregion

		#region Methods

		private void IncludeScript() {
			Page page = this.context.Handler as Page;
			if (page != null) {
				ClientScriptManager sm = page.ClientScript;
				string jsKey = "language";
				Type jsType = typeof(MultilanguageJsResource);
				string jsFile = this.GetDirectoryForJs();
				if (!sm.IsClientScriptIncludeRegistered(jsType, jsKey))
					sm.RegisterClientScriptInclude(jsType, jsKey, jsFile);
			}
		}

		private string GetDirectoryForJs() {
			string jsDir = "/ResourceScripts/";

			if (diJs == null) {
				diJs = new DirectoryInfo(this.context.Server.MapPath(jsDir));
				if (!diJs.Exists)
					diJs.Create();
			}
			return jsDir + this.fiBaseResourceFile.Name.ReplaceEx(".resx", "." + this.includeLanguage.Name + ".resx.js");
		}

		private void SetFileInfos(string resourceFileName) {
			this.resourceFileName = resourceFileName;
			this.fiBaseResourceFile = new FileInfo(this.context.Server.MapPath(this.resourceFileName));
			this.fiLangResourceFile = new FileInfo(this.context.Server.MapPath(this.resourceFileName.ReplaceEx(".resx", "." + this.includeLanguage.Name + ".resx")));
			if (!fiLangResourceFile.Exists)
				fiLangResourceFile = new FileInfo(this.context.Server.MapPath(this.resourceFileName.ReplaceEx(".resx", "." + this.includeLanguage.Name.Split('-')[0] + ".resx")));

			this.jsLangResourceFile = new FileInfo(this.context.Server.MapPath(this.GetDirectoryForJs()));
		}

		private void EnsureSetJsFiles() {


			DateTime resourceFileTime = DateTime.MinValue;
			DateTime jsFileTime = DateTime.MinValue;
			if (fiBaseResourceFile.Exists)
				resourceFileTime = fiBaseResourceFile.LastWriteTime;
			if (fiLangResourceFile.Exists && fiLangResourceFile.LastWriteTime > resourceFileTime)
				resourceFileTime = fiLangResourceFile.LastWriteTime;
			if (jsLangResourceFile.Exists)
				jsFileTime = jsLangResourceFile.LastWriteTime;

			if (resourceFileTime > jsFileTime)
				this.CreateJsFile(fiBaseResourceFile, fiLangResourceFile, jsLangResourceFile);
		}

		private void CreateJsFile(FileInfo fiBaseResourceFile, FileInfo fiLangResourceFile, FileInfo jsLangResourceFile) {
			string jsCode = this.GetJsFileContent(fiBaseResourceFile, fiLangResourceFile);
			using (FileStream fs = jsLangResourceFile.Open(FileMode.Create, FileAccess.Write, FileShare.Write))
			using (StreamWriter sw = new StreamWriter(fs)) {
				sw.Write(jsCode);
				sw.Close();
				fs.Close();
				sw.Dispose();
				fs.Dispose();
			}
		}

		private string GetJsFileContent(FileInfo fiBaseResourceFile, FileInfo fiLangResourceFile) {
			Dictionary<string, string> baseData = this.ReadRsxFile(fiBaseResourceFile);
			Dictionary<string, string> langData = this.ReadRsxFile(fiLangResourceFile);

			if (baseData.Count == 0) return "";

			string jsLangKey = this.includeLanguage.Name;

			StringBuilder sb = new StringBuilder();
			sb.AppendFormat("var language = {{Current: '{0}',", jsLangKey);

			foreach (KeyValuePair<string, string> baseItem in baseData) {
				string key = baseItem.Key;
				string baseValue = this.ClearForJSInline(baseItem.Value);
				string langValue = "";

				if (langData.ContainsKey(key))
					langValue = this.ClearForJSInline(langData[key]);

				string value = langValue;
				if (string.IsNullOrEmpty(value)) value = baseValue;

				sb.AppendFormat(" {0}:  '{1}',", key, value);
			}

			sb.Append("Exists: function(key) { if(this[key] === undefined) return false; else return true; }}");
			return sb.ToString();
		}

		private Dictionary<string, string> ReadRsxFile(FileInfo fi) {
			Dictionary<string, string> data = new Dictionary<string, string>();
			if (fi.Exists) {
				using (FileStream fs = fi.Open(FileMode.Open, FileAccess.Read, FileShare.Read)) {
					ResXResourceReader rrx = new ResXResourceReader(fs);
					IDictionaryEnumerator rren = rrx.GetEnumerator();
					while (rren.MoveNext()) {
						data.Add(rren.Key.ToString(), rren.Value.ToString());
					}
				}
			}
			return data;
		}

		private string ClearForJSInline(string jsTextCode) {
			return jsTextCode.ReplaceEx("'", @"\'").ReplaceEx("\r", " ").ReplaceEx("\n", " ");
		}

		#endregion


	}
}